package com.xy.shiro;

import com.auth0.jwt.internal.org.apache.commons.codec.digest.DigestUtils;
import com.auth0.jwt.internal.org.apache.commons.lang3.StringUtils;
import com.xy.modular.basics.entity.user.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.web.filter.authc.AuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * 这个重点在于你要继承哪个shiroFilter,主要还是根据需求进行不同的继承,如果自定义的内容很多还是继承较高的父级,如果功能需求不多,
 * 尽量还是使用shiro过滤器的一些原有的功能,我自己尝试了几个,最后继承了最终的实现类AuthenticationFilter;
 * 这过滤器就是我们过滤器链上key为的authc的过滤器.同时也对ajax做了区分.不能给ajax返回一个页面吧.
 * 说明一下:这两个重写的方法.filter是否允许是由这两个方法决定的. 底层代码是:
 * 
 * return isAccessAllowed() || onAccessDenied()
 * 
 * 1
 * 
 * isAccessAllowed:是否允许访问,当为true时就会允许,不需要执行onAccessDenied了.
 * onAccessDenied:只有当isAccessAllowed为false为false时才会执行,所以可以理解为,不允许访问后要怎么告诉用户的方法.
 * 或是一些其他的操作. ———————————————— 版权声明：本文为CSDN博主「‖倾城丶之蓝。」的原创文章，遵循 CC 4.0 BY-SA
 * 版权协议，转载请附上原文出处链接及本声明。
 * 原文链接：https://blog.csdn.net/sqlgao22/article/details/99186391
 * 
 * @author BCK
 *
 */
public class ShiroFilter  extends AuthenticationFilter {

	static Logger log = LoggerFactory.getLogger(ShiroFilter.class);

	//加密的字符串,相当于签名

	private static final String SINGNATURE_TOKEN = "加密token";

	@Override
	protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse response, Object mappedValue) {
		//这里只有返回false才会执行onAccessDenied方法,因为
		// return super.isAccessAllowed(request, response, mappedValue);

		HttpServletRequest request = (HttpServletRequest) servletRequest;
		// String token = request.getHeader(TokenUtil.tokenHeard);
		String token = getRequestToken((HttpServletRequest) servletRequest);
		log.debug("================"+token);
		if (null == token||"".equals(token)) {
			log.debug("-------------------token为空");
			return false;
		}
		//验证token的真实性
		try {
			TokenUtil.getTokenBody(token);
		} catch (Exception e) {
			e.printStackTrace();
			log.debug("----------------token有问题");
			return false;
		}
		log.debug("加密token");
		return true;
	}

	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {

		String token = getRequestToken((HttpServletRequest) request);
		String login = ((HttpServletRequest) request).getServletPath();
		log.debug("onAccessDenied------token----------"+token);

		//如果为登录,就放行
		if ("/user/login".equals(login)){
			return true;
		}
		if (StringUtils.isBlank(token)){
			return false;
		}

		//从当前shiro中获得用户信息
		ShiroUser shiroUser = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
		//对当前ID进行SHA256加密
		log.debug("无效token------encryptionKey----------"+shiroUser.getName());

		String encryptionKey= DigestUtils.sha256Hex(SINGNATURE_TOKEN+shiroUser.getName());
		if (encryptionKey.equals(token)){
			return true;
		}else{
			log.debug("无效token------encryptionKey----------"+encryptionKey);
		}
		return false;
	}
	private String getRequestToken(HttpServletRequest request){
		//默认从请求头中获得token
		String token = request.getHeader("Authentication");
		//如果header中不存在token，则从参数中获取token
		if(StringUtils.isBlank(token)){
			token = request.getParameter("Authentication");
		}
		log.debug("Authentication----------"+token);
		return token;
	}
}
